import cPickle
import sys
import os
from collections import Counter
from collections import defaultdict
from operator import itemgetter
import numpy as np 
from numpy import arange,array,ones,linalg,bincount
from datetime import datetime
xindex={}
map_db="az_map.db"
c1_db="clus_1.db"
c2_db="clus_2.db"
cno_db="clus_no.db"
for x in open("xindex.db"):
	xindex[x.strip("\n")]=1

tm_index=sorted(xindex)

def init_bl():
	bl=cPickle.load(open("bl.db"))
	return bl

def init_db(dbn,blacklist):
	db=cPickle.load(open(dbn))
	for k in db.keys():
		if db[k] in blacklist:
			db.pop(k)
	return db

def init_tm_ip_matrix(db):
	m={}
	for k in db:
		c=db[k]
		ip,tm=k
		if tm not in xindex:
			continue
		if c not in m:
			m[c]={}
		if tm in m[c]:
			m[c][tm].append(ip)
		else:
			m[c][tm]=[ip]
	return m

cls_blacklist=init_bl()
#cls_blacklist={}
#db=init_db(c2_db,cls_blacklist)


def fix_data(tm_ip):
	st=sorted(tm_ip)[0]
	ed=sorted(tm_ip)[-1]
	st_id=tm_index.index(st)
	ed_id=tm_index.index(ed)
	c=0
	for tm_id in range(st_id,ed_id+1):
		tm=tm_index[tm_id]
		#add missing data
		if tm not in tm_ip:
			ptm=tm_index[tm_id-1]
			atm=tm_index[tm_id+1]
			if (ptm in tm_ip) and (atm in tm_ip):
				if (len(tm_ip[ptm])==1 and len(tm_ip[atm])==1):
					tm_ip[tm]=tm_ip[ptm]
					continue
				if len(set(tm_ip[ptm])&set(tm_ip[atm]))!=0 and (len(tm_ip[ptm])==1 or len(tm_ip[atm])==1):
					tm_ip[tm]=tm_ip[ptm]
					continue

	#fill the valley
	tms=sorted(tm_ip)
	for tm_id in xrange(len(tms)-1):
		tm=tms[tm_id]
		ptm=tms[tm_id-1]
		atm=tms[tm_id+1]
		if len(tm_ip[ptm])==len(tm_ip[tm])+1 and len(tm_ip[atm])==len(tm_ip[tm])+1:
			if set(tm_ip[tm])&set(tm_ip[ptm])==set(tm_ip[tm]):
				tm_ip[tm]=tm_ip[ptm]
			else:
				tm_ip[tm]=tm_ip[atm]
	return tm_ip

#if ip not change and # not change
def pt_stable(tm_ip):
	tmp={}
	for k in tm_ip:
		tmp[len(tm_ip[k])]=1
	if len(tmp)==1:
		return True
	return False

def pt_ab_increse(tm_ip):
	tmp=[]
	for tm in sorted(tm_ip):
		tmp.append(len(tm_ip[tm]))
	for k in xrange(len(tmp)-1):
		if tmp[k]>tmp[k+1]:
			return False
	return True

def pt_ab_decrease(tm_ip):
	tmp=[]
	for tm in sorted(tm_ip):
		tmp.append(len(tm_ip[tm]))
	for k in xrange(len(tmp)-1):
		if tmp[k]<tmp[k+1]:
			return False
	return True

def pt_peak_once(tm_ip):
	tmp=[]
	for tm in sorted(tm_ip):
		tmp.append(len(tm_ip[tm]))
	t=[tmp[0]]
	for v in tmp:
		if t[-1]!=v:
			t.append(v)
	pos=t.index(max(t))
	for i in range(0,pos):
		if t[i]>t[i+1]:
			return False
	for i in range(pos,len(t)-1):
		if t[i]<t[i+1]:
			return False
	return True

def pt_valley_once(tm_ip):
	tmp=[]
	for tm in sorted(tm_ip):
		tmp.append(len(tm_ip[tm]))
	t=[tmp[0]]
	for v in tmp:
		if t[-1]!=v:
			t.append(v)
	pos=t.index(min(t))
	for i in range(0,pos):
		if t[i]<t[i+1]:
			return False
	for i in range(pos,len(t)-1):
		if t[i]>t[i+1]:
			return False
	return True

def break_down_by_server(web_no_list):
	db=init_db(cno_db,cls_blacklist)
	tmp=[]
	for k in db:
		if db[k] in web_no_list:
			tmp.append(k[4])
	c=Counter(tmp)
	c=sorted(c.items(),key=itemgetter(1),reverse=True)[:20]
	return c

def break_down_by_tmpl(web_no_list):
	db=init_db(cno_db,cls_blacklist)
	tmp=[]
	for k in db:
		if db[k] in web_no_list:
			tmp.append(k[2])
	c=Counter(tmp)
	c=sorted(c.items(),key=itemgetter(1),reverse=True)[:20]
	return c

def calc_life(d1,d2):
	dft=datetime.strptime(d2,"%Y-%m-%d")-datetime.strptime(d1,"%Y-%m-%d")
	return dft.days

def real_life_time(tm_ip):
	st=sorted(tm_ip)[0]
	st_ip=tm_ip[st]
	c=0
	life=0
	used_tm={}
	for tm_id in xrange(len(tm_index)-1):
		ctm=tm_index[tm_id]
		atm=tm_index[tm_id+1]
		if ctm in tm_ip and atm in tm_ip:
			#if ctm in used_tm:
			life+=calc_life(ctm,atm)
			#else:
			#	life+=calc_life(ctm,atm)+1
			used_tm[atm]=1
		elif ctm in tm_ip and atm not in tm_ip:
			if ctm in used_tm:
				continue
			life+=1
	return life

def expect_life_time(tm_ip):
	st=sorted(tm_ip)[0]
	ed=sorted(tm_ip)[-1]
	return calc_life(st,ed)+1

def life_time(tm_ip):
	st=sorted(tm_ip)[0]
	ed=sorted(tm_ip)[-1]
	st_id=tm_index.index(st)
	ed_id=tm_index.index(ed)
	return len(tm_ip),ed_id-st_id+1

def ip_update(tm_ip):
	st=sorted(tm_ip)[0]
	for tm in sorted(tm_ip):
		op=abs(len(tm_ip[tm])-len(set(tm_ip[tm])&set(st_ip)))
		st_ip=tm_ip[tm]
		c+=op
	return c

def maintain_time1(tm_ip):
	st=sorted(tm_ip)[0]
	ed=sorted(tm_ip)[-1]
	st_ip=tm_ip[st]
	pip=len(st_ip)
	flag=False
	for tm_id in xrange(len(tm_index)-1):
		ctm=tm_index[tm_id]
		if ctm<st or ctm>ed:
			continue
		atm=tm_index[tm_id+1]
		if ctm in tm_ip and flag:
			cip=len(tm_ip[ctm])
			if cip!=pip:
				return True
			else:
				flag=False
				pip=cip
		if ctm in tm_ip and atm not in tm_ip:
			pip=len(tm_ip[ctm])
			flag=True
	return False

def maintain_time(tm_ip):
	st=sorted(tm_ip)[0]
	ed=sorted(tm_ip)[-1]
	st_id=tm_index.index(st)
	ed_id=tm_index.index(ed)
	etime=tm_index[st_id:ed_id+1]
	rtime=sorted(tm_ip)
	mtime=list(set(etime)-set(rtime))

	tmp=[]
	for tm in tm_index[st_id:ed_id+1]:
		if tm in mtime:
			tmp.append("#")
		else:
			tmp.append(len(tm_ip[tm]))
	out=[tmp[0]]
	for t in tmp:
		if t=="#" and t!=out[-1]:
			out.append(t)
		if t!="#":
			out.append(t)
	out="".join([str(v) for v in out])
	while out.find("#")!=-1:
		pos=out.find("#")
		p=0
		if pos==len(out)-2:
			p=out[pos+1]
		else:
			p=out[pos+2]
		if out[pos-1]!=p:
			return True
		out=out[pos+1:]
	return False
	

def miss_data(tm_ip):
	tmp=[]
	for tm in sorted(tm_ip):
		tmp.append(len(tm_ip[tm]))
	#print tmp
	"""
	base=np.argmax(np.bincount(tmp))

	tmp=[v for v in tmp if v > base]
	if tmp:
		mx2=np.argmax(np.bincount(tmp))
		print mx1,mx2,tmp[-1]
	"""


def test():
	m=init_tm_ip_matrix(init_db(c2_db,cls_blacklist))
	db=init_db(cno_db,cls_blacklist)
	c=0
	c1=0
	c2=0
	c3=0
	c4=0
	out=[]
	out1=0
	out2=[]
	out3=[]
	for k in m:
		m[k]=fix_data(m[k])
		if pt_stable(m[k]):
			c=c+1
			#out.append(int(float(real_life_time(m[k]))*100/expect_life_time(m[k])))
			continue
		if pt_ab_increse(m[k]):
			c1=c1+1
			r,e=life_time(m[k])
			if r!=e:
				out1+=1
				out.append(maintain_time(m[k]))
			continue
		if pt_ab_decrease(m[k]):
			c2=c2+1
			
			continue
		if pt_peak_once(m[k]):
			c3=c3+1
			
			continue
		if pt_valley_once(m[k]):
			c4=c4+1
			continue
		#miss_data(m[k])
		
	print c,c1,c2,c3,c4,len(m)
	print Counter(out)
	print out1


	


	





			








if __name__ == '__main__':
	test()